package risoe.syslab.fhnew.hw;

/*
 * Copyright (c) 2012-2014, Technical University of Denmark (DTU)
 * All rights reserved.
 * 
 * The Flexhouse 2.0 platform ("this software") is licensed under the
 * BSD 3-clause license.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   - Neither the name of DTU nor the names of its contributors may be used to
 *     endorse or promote products derived from this software without specific
 *     prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE TECHNICAL UNIVERSITY OF DENMARK BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.DatatypeConverter;
import risoe.syslab.fhnew.config.ActuatorConfig;
import risoe.syslab.fhnew.config.HWInterfaceConfig;
import risoe.syslab.fhnew.config.AirConInterfaceConfig;
import risoe.syslab.fhnew.config.SensorConfig;

/**
 * Hardware Interface for communicating with Air Conditioners using IR transmission
 * @author M. Svendsen
 */
public class AirConInterface extends HardwareInterface implements ConnectionManagerInterface{
	public static final Pattern MESSAGE_PATTERN = Pattern.compile("^AUTO([0-9][0-9])([0-9][0-9])$");
	private static final byte[] MESSAGE_PREFIX;
	static {
		final int[] mp = {0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
		MESSAGE_PREFIX = new byte[mp.length];
		for (int i = 0; i < mp.length; i++) {
			MESSAGE_PREFIX[i] = (byte)(mp[i] & 0xFF);
		}
	}
	
	private ConnectionManager mConnectionManager;

	// This is beautiful on the eyes...
	private static final Map<String, byte[]> mCommandMap;
	static {
		Map<String, byte[]> aMap = new HashMap<String, byte[]>();
		aMap.put("OFF", DatatypeConverter.parseHexBinary("c69b0600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303130303030303030303030313130303131313031303131313131303030303030303030303030303030303030303030303030303131313031313031303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303031303031313030"));
		aMap.put("AUTO3005", DatatypeConverter.parseHexBinary("c6930600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130313030303031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303130303030313030"));
		aMap.put("AUTO3009", DatatypeConverter.parseHexBinary("c6950600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130313031303031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303130313030313030"));
		aMap.put("AUTO3011", DatatypeConverter.parseHexBinary("c6950600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130313030313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313130303030313030"));
		aMap.put("AUTO3014", DatatypeConverter.parseHexBinary("c6950600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130303130313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313031303030313030"));
		aMap.put("AUTO3015", DatatypeConverter.parseHexBinary("c6970600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130313130313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313131303030313030"));
		aMap.put("AUTO3016", DatatypeConverter.parseHexBinary("c6950600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130303031313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313030313030313030"));
		aMap.put("AUTO3019", DatatypeConverter.parseHexBinary("c6970600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303131313131313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303030303130313030"));
		aMap.put("AUTO3020", DatatypeConverter.parseHexBinary("c6930600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130303030303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303130303030313030"));
		aMap.put("AUTO3023", DatatypeConverter.parseHexBinary("c6970600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303131313130303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313030313030313030"));
		aMap.put("AUTO3024", DatatypeConverter.parseHexBinary("c6970600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303131303031303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313130313030313030"));
		aMap.put("AUTO3027", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130313131303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303030303130313030"));
		aMap.put("AUTO3029", DatatypeConverter.parseHexBinary("c6970600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303131313030313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303131303030313030"));
		aMap.put("AUTO3030", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303131303130313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303030313030313030"));
		aMap.put("AUTO3031", DatatypeConverter.parseHexBinary("c6980600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303131313130313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303130313030313030"));
		aMap.put("AUTO3034", DatatypeConverter.parseHexBinary("c6990600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303031303131303130303131313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313131313030313030"));
		aMap.put("AUTO1605", DatatypeConverter.parseHexBinary("c6920600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130313030303031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303031303030313030"));
		aMap.put("AUTO1609", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131313031303031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313031313030313030"));
		aMap.put("AUTO1611", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131313131303031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313030303130313030"));
		aMap.put("AUTO1616", DatatypeConverter.parseHexBinary("c6950600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130303031313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313130313030313030"));
		aMap.put("AUTO1617", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130313031313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313031313030313030"));
		aMap.put("AUTO1618", DatatypeConverter.parseHexBinary("c6970600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130303131313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313131313030313030"));
		aMap.put("AUTO1619", DatatypeConverter.parseHexBinary("c6970600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131313131313031313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303130303130313030"));
		aMap.put("AUTO1620", DatatypeConverter.parseHexBinary("c6940600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131303030303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313031303030313030"));
		aMap.put("AUTO1621", DatatypeConverter.parseHexBinary("c6940600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130313030303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303131303030313030"));
		aMap.put("AUTO1622", DatatypeConverter.parseHexBinary("c6950600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131303130303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313030313030313030"));
		aMap.put("AUTO1623", DatatypeConverter.parseHexBinary("c6950600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130313130303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303130313030313030"));
		aMap.put("AUTO1624", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131303031303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313031313030313030"));
		aMap.put("AUTO1625", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130313031303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303131313030313030"));
		aMap.put("AUTO1626", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131303131303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313030303130313030"));
		aMap.put("AUTO1627", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130313131303131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303130303130313030"));
		aMap.put("AUTO1628", DatatypeConverter.parseHexBinary("c6940600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130303030313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313031303030313030"));
		aMap.put("AUTO1629", DatatypeConverter.parseHexBinary("c6950600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131313030313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303030313030313030"));
		aMap.put("AUTO1630", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131303130313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303130313030313030"));
		aMap.put("AUTO1631", DatatypeConverter.parseHexBinary("c6970600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130313130313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313130313030313030"));
		aMap.put("AUTO1632", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130303031313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313031313030313030"));
		aMap.put("AUTO1633", DatatypeConverter.parseHexBinary("c6960600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303131313031313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030303030303130313030"));
		aMap.put("AUTO1635", DatatypeConverter.parseHexBinary("c6980600ffff9a2701ce0030009a0000000000000000000000a801390038000000000000000000000000010053303030303030313030303030303030303030313031303030303030303030303130313131303131303031303030303030303030313130303130313131313131313131303030313030303030303030303030303030303030303030303030303030303030303030303031303030303030303030303030303030303030303030303030303030303030303030303030303030313130303130313030"));
		mCommandMap = Collections.unmodifiableMap(aMap);
	}

	public enum Mode {
		Off, // These are the only values we care about
		Auto;
	};

	private HashMap<String, InetAddress> mDeviceMap;
	private final int mPort;
	private DatagramSocket mSocket;
	private DatagramPacket mLastPacket = null;

	public AirConInterface(HWInterfaceConfig hic) {
		super(hic);
		mPort = ((AirConInterfaceConfig)hic).getPort();
	}

	@Override
	protected void startInterfaceImpl(ArrayList<SensorConfig> sensors,
			ArrayList<ActuatorConfig> actuators) {

		// We only deal with actuators here (Aircons)
		mDeviceMap = new HashMap<String, InetAddress>(actuators.size());
		for (ActuatorConfig act : actuators){
			InetAddress addr;
			try {
				addr = InetAddress.getByName(act.getInterfaceAttributes().get("ip"));
				mDeviceMap.put(act.getName(), addr);
			} catch (UnknownHostException e) {
				System.out.println(getName()+" error resolving ip for device "+act.getName());
				getLogger().logEvent(getName(), "Lookup Error", "Error resolving ip for device: "+act.getName());
			}
		}
		
		mConnectionManager = new ConnectionManager(this, 30000);
		mConnectionManager.startConnection();
	}
	
	@Override
	public boolean connect() {
		try {
			mSocket = new DatagramSocket();
			if (mLastPacket != null){
				return probeConnection();
			}
			return true;
		} catch (SocketException e) {
			// Connection failed
		}
		return false;
	}
	
	@Override
	public void disconnect() {
		if (mSocket != null){
			mSocket.close();
			mSocket = null;
		}
	}
	
	@Override
	public boolean probeConnection() {
		synchronized (mSocket) {
			try {
				mSocket.send(mLastPacket);
				return true;
			} catch (IOException e) {
				// Send failed - connection must be down
			}
		}
		return false;
	}

	@Override
	protected void stopInterfaceImpl() {
		if(mSocket != null){
			mSocket.close();
		}
	}

	@Override
	public boolean isConnected() {
		return mConnectionManager.isConnected();
	}

	@Override
	public void applyActuation(Actuator actuator) {
		if (!mConnectionManager.isConnected()){
			getLogger().logEvent(getName(), "Error", "Cannot send actuation request - interface is not connected");
			return;
		}
		
		InetAddress addr = mDeviceMap.get(actuator.getName());
		if (addr != null){
			double setpoint = actuator.getSetpoint().value;

			// Handle actuation
			if (setpoint == 0.0){
				// Turn off aircon
				byte[] command = mCommandMap.get("OFF");
				sendCommand(addr, command);
			}
			else{
				// Turn on aircon and choose the nearest setpoint
				double bestMatchValue = Double.POSITIVE_INFINITY;
				byte[] bestMatchCmd = null;
				for (Map.Entry<String, byte[]> entry : mCommandMap.entrySet()) {
					Matcher m = MESSAGE_PATTERN.matcher(entry.getKey());
					if ( m.matches() ) {
						double cmdSetpoint = Double.valueOf(m.group( 1 ));
						@SuppressWarnings("unused")
            double cmdCurrent  = Double.valueOf(m.group( 2 ));
						// TODO: Fix this / Reimplement
						// double match = Math.abs( temperature-cmdSetpoint )() + Math.abs( currentTemperature-cmdCurrent );
						double match = Math.abs(setpoint-cmdSetpoint);
						if (match < bestMatchValue ) {
							bestMatchValue = match;
							bestMatchCmd = entry.getValue();
						}
					}
				}

				if (bestMatchCmd != null){
					sendCommand(addr, bestMatchCmd);
				}
				else{
					getLogger().logEvent(getName(), "Command Mismatch", "Error matching a command with request: "+setpoint);
				}
			}
		}
		else{
			getLogger().logEvent(getName(), "Lookup Error", "Error recognizing device "+actuator.getName());
			System.out.println(getName()+" error recognizing device "+actuator.getName());
		}
	}

	public void sendCommand(InetAddress addr, byte[] message){
		// Assemble data
		byte[] result = Arrays.copyOf(MESSAGE_PREFIX, MESSAGE_PREFIX.length + message.length);
		System.arraycopy(message, 0, result, MESSAGE_PREFIX.length, message.length);

		try {
			mLastPacket = new DatagramPacket(result, result.length, addr, mPort);
			synchronized (mSocket) {
				mSocket.send(mLastPacket);
			}
		} catch (UnknownHostException e) {
			mConnectionManager.onDisconnected();
		} catch (SocketException e) {
			mConnectionManager.onDisconnected();
		} catch(IOException e) { 
			mConnectionManager.onDisconnected();
		} 
	}
}
